package cn.lg.soar.boot.fc.service.impl;

import cn.lg.soar.boot.fc.entity.*;
import cn.lg.soar.boot.fc.entity.bo.FloorBo;
import cn.lg.soar.boot.fc.entity.importExcel.FloorIo;
import cn.lg.soar.boot.fc.entity.vo.*;
import cn.lg.soar.boot.fc.params.RoomParams;
import cn.lg.soar.boot.fc.service.*;
import cn.lg.soar.common.data.msg.I18n;
import cn.lg.soar.common.model.HttpResult;
import cn.lg.soar.common.model.PageQuery;
import cn.lg.soar.common.model.PageResult;
import cn.lg.soar.common.util.AssertUtil;
import cn.lg.soar.common.util.ParameterUtil;
import cn.lg.soar.core.util.easyexcel.ExcelUtil;
import cn.lg.soar.database.query.QueryParams;
import cn.lg.soar.database.query.SqueryWapper;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.lg.soar.database.base.service.impl.BaseServiceImpl;
import cn.lg.soar.boot.fc.mapper.FloorMapper;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 楼层表
 * @author ZhuanZ（无密码）
 * @since 2025-01-10
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Service
public class FloorServiceImpl extends BaseServiceImpl<FloorMapper, Floor> implements FloorService {

    @Autowired
    private CampusService campusService;

    @Autowired
    private BuildingService buildingService;

    @Autowired
    private UnitService unitService;

    @Autowired
    private RoomService roomService;

    @Override
    public HttpResult<Serializable> create(FloorBo floorBo) {

        ParameterUtil.notNull(floorBo, "数据不能为空");

        Floor floor = new Floor();

        BeanUtils.copyProperties(floorBo, floor);

        // 父级的参数 关联
        String parentId = floorBo.getParentId();
        // 祖宗
        String campusIdSearch = "";
        String buildingIdSearch = "";
        String unitIdSearch = "";

        // 1-3-0-0
        String[] searchStr = parentId.split("-");

        if (4 <= searchStr.length) {
            campusIdSearch = !"0".equals(searchStr[0]) ? searchStr[0]: "";
            buildingIdSearch = !"0".equals(searchStr[1]) ? searchStr[1]: "";
            unitIdSearch = !"0".equals(searchStr[2]) ? searchStr[2]: "";
        }

        if (StringUtils.isNotBlank(campusIdSearch)) {
            floor.setCampusId(Long.valueOf(campusIdSearch));
        }
        if (StringUtils.isNotBlank(buildingIdSearch)) {
            floor.setBuildingId(Long.valueOf(buildingIdSearch));
        }
        if (StringUtils.isNotBlank(unitIdSearch)) {
            floor.setUnitId(Long.valueOf(unitIdSearch));
        }

        boolean checkFlag =
                StringUtils.isBlank(campusIdSearch) || StringUtils.isBlank(buildingIdSearch) || StringUtils.isBlank(unitIdSearch);

        if (checkFlag) {
            return HttpResult.fail("4000", "楼层关联层级不正确，请重新选择", "error");
        }

        // 父级的参数 关联 end
        AssertUtil.isTrue(this.save(floor), "创建失败");


        return HttpResult.<Serializable>success("创建成功").setData("success");
    }

    @Override
    public HttpResult<Void> update(FloorBo floorBo) {

        ParameterUtil.notNull(floorBo, "数据不能为空");
        Floor floor = new Floor();
        BeanUtils.copyProperties(floorBo, floor);

        // 父级的参数 关联
        String parentId = floorBo.getParentId();
        // 祖宗
        String campusIdSearch = "";
        String buildingIdSearch = "";
        String unitIdSearch = "";

        // 1-3-0-0
        String[] searchStr = parentId.split("-");

        if (4 <= searchStr.length) {
            campusIdSearch = !"0".equals(searchStr[0]) ? searchStr[0]: "";
            buildingIdSearch = !"0".equals(searchStr[1]) ? searchStr[1]: "";
            unitIdSearch = !"0".equals(searchStr[2]) ? searchStr[2]: "";
        }

        if (StringUtils.isNotBlank(campusIdSearch)) {
            floor.setCampusId(Long.valueOf(campusIdSearch));
        }
        if (StringUtils.isNotBlank(buildingIdSearch)) {
            floor.setBuildingId(Long.valueOf(buildingIdSearch));
        }
        if (StringUtils.isNotBlank(unitIdSearch)) {
            floor.setUnitId(Long.valueOf(unitIdSearch));
        }

        boolean checkFlag =
                StringUtils.isBlank(campusIdSearch) || StringUtils.isBlank(buildingIdSearch) || StringUtils.isBlank(unitIdSearch);

        if (checkFlag) {
            return HttpResult.fail("4000", "楼层关联层级不正确，请重新选择", "error");
        }

        // 父级的参数 关联 end
        AssertUtil.isTrue(this.updateById(floor), "更新失败");
        return HttpResult.success("更新成功");
    }

    @Override
    public Floor getData(Long id) {
        if (Objects.isNull(id)) {
            return new Floor();
        }

        Floor floor = this.getOne(Wrappers.<Floor>lambdaQuery().eq(Floor::getId, id));
        if (null == floor) {
            floor = new Floor();
        }
        return floor;
    }

    @Override
    public FloorVo getVoData(Long id) {

        FloorVo floorVo = new FloorVo();
        if (Objects.isNull(id)) {
            return floorVo;
        }

        Floor floor = this.getData(id);
        BeanUtils.copyProperties(floor, floorVo);
        // 不做其他easy 对象的封装，有需要在加

        // 校区简单vo
        CampusEasyVo campusEasyVo = campusService.getEasyVoData(floorVo.getCampusId());
        floorVo.setCampusEasyVo(campusEasyVo);

        // 楼栋简单vo
        BuildingEasyVo buildingEasyVo = buildingService.getEasyVoData(floorVo.getBuildingId());
        floorVo.setBuildingEasyVo(buildingEasyVo);

        // 单元简单vo
        UnitEasyVo unitEasyVo = unitService.getEasyVoData(floorVo.getUnitId());
        floorVo.setUnitEasyVo(unitEasyVo);

        return floorVo;
    }

    @Override
    public FloorEasyVo getEasyVoData(Long id) {

        FloorEasyVo floorEasyVo = new FloorEasyVo();
        if (Objects.isNull(id)) {
            return floorEasyVo;
        }

        Floor floor = this.getData(id);
        if (null == floor) {
            return floorEasyVo;
        }
        BeanUtils.copyProperties(floor, floorEasyVo);
        return floorEasyVo;
    }

    @Override
    public PageResult<FloorVo> queryResultVo(PageQuery pageQuery, QueryParams params) {

        PageResult<FloorVo> pageResultVo = new PageResult<>();

        SqueryWapper<Floor> squeryWapper = new SqueryWapper<>(Floor.class);
        PageResult<Floor> pageResult = squeryWapper.query(this, pageQuery, params);

        // 对象拷贝
        BeanUtils.copyProperties(pageResult, pageResultVo);

        // vo单独封装
        List<FloorVo> list = new ArrayList<>();

        pageResult.getList().forEach(item-> {

            FloorVo floorVo = new FloorVo();
            BeanUtils.copyProperties(item, floorVo);

            // 封装简单的校区信息
            floorVo.setCampusEasyVo(campusService.getEasyVoData(item.getCampusId()));
            // 封装简单的楼号信息
            floorVo.setBuildingEasyVo(buildingService.getEasyVoData(item.getBuildingId()));
            // 封装简单的单元信息
            floorVo.setUnitEasyVo(unitService.getEasyVoData(item.getUnitId()));

            list.add(floorVo);
        });

        pageResultVo.setList(list);
        return pageResultVo;
    }

    @Override
    public PageResult<JSONObject> queryResultEasyVo(PageQuery pageQuery, QueryParams params, RoomParams roomParams) {

        PageResult<JSONObject> pageResultVo = new PageResult<>();

        SqueryWapper squeryWapper = new SqueryWapper(Floor.class);

        // 树状菜单检索兼容page检索
        if (StringUtils.isNotBlank(roomParams.getSearchIds())) {
            // 祖宗
            String campusIdSearch = "";
            String buildingIdSearch = "";
            String unitIdSearch = "";
            String floorIdSearch = "";
            // 1-3-0-0
            String[] searchStr = roomParams.getSearchIds().split("-");
            if (4 >= searchStr.length) {
                campusIdSearch = !"0".equals(searchStr[0]) ? searchStr[0]: "";
                buildingIdSearch = !"0".equals(searchStr[1]) ? searchStr[1]: "";
                unitIdSearch = !"0".equals(searchStr[2]) ? searchStr[2]: "";
                floorIdSearch = !"0".equals(searchStr[3]) ? searchStr[3]: "";
            }

            List<String> f = params.getF();
            if (null == f) {
                f = new ArrayList<>();
            }
            if (StringUtils.isNotBlank(campusIdSearch)) {
                f.add("campusId-like~" + campusIdSearch);
            }
            if (StringUtils.isNotBlank(buildingIdSearch)) {
                f.add("buildingId-like~" + buildingIdSearch);
            }
            if (StringUtils.isNotBlank(unitIdSearch)) {
                f.add("unitId-like~" + unitIdSearch);
            }
            if (StringUtils.isNotBlank(floorIdSearch)) {
                f.add("floorId-like~" + floorIdSearch);
            }

            params.setF(f);
        }
        PageResult<Floor> pageResult = squeryWapper.query(this, pageQuery, params);

        BeanUtils.copyProperties(pageResult, pageResultVo);

        // 数据vp
        List<JSONObject> listVo = new ArrayList<>();

        pageResult.getList().forEach(item-> {
            JSONObject jsonObject = new JSONObject();

            jsonObject.put("value", item.getId());
            jsonObject.put("label", item.getName());
            // 是否有房间信息
            JSONArray jsonArray = new JSONArray();

            // 取房间信息
            QueryParams rParams = new QueryParams();
            List<String> floorF = new ArrayList<>();
            floorF.add("campusId-eq~" + item.getCampusId());
            floorF.add("buildingId-eq~" + item.getBuildingId());
            floorF.add("unitId-eq~" + item.getUnitId());
            floorF.add("floorId-eq~" + item.getId());
            rParams.setF(floorF);

            List<Room> rList = roomService.getListByOtherId(rParams);
            rList.forEach(rItem-> {
                JSONObject rObj = new JSONObject();
                rObj.put("value", rItem.getId());
                rObj.put("label", rItem.getRoomCode());
                jsonArray.add(rObj);
            });

            if (0 < jsonArray.size()) {
                jsonObject.put("children", jsonArray);
            }
            listVo.add(jsonObject);
        });

        pageResultVo.setList(listVo);
        return pageResultVo;
    }

    @Override
    public List<FloorVo> getListVoByOtherId(QueryParams params) {

        List<FloorVo> listVo = new ArrayList<>();

        // 架构get 请求参数格式：
//        [name-like~楼栋1, area-like~100]
        List<String> f = params.getF();
        if (2 >= f.size()) {
            return listVo;
        }

        String campusIdStr = f.get(0);
        String buildingIdStr = f.get(1);
        String unitIdStr = f.get(2);
        if (-1 >= campusIdStr.indexOf("campusId")) {
            return listVo;
        }
        if (-1 >= buildingIdStr.indexOf("buildingId")) {
            return listVo;
        }
        if (-1 >= unitIdStr.indexOf("unitId")) {
            return listVo;
        }


        String[] campTemp = campusIdStr.split(params.VALUE_JOIN);
        String[] buildTemp = buildingIdStr.split(params.VALUE_JOIN);
        String[] unitTemp = unitIdStr.split(params.VALUE_JOIN);

        if (1 >= campTemp.length || 1 >= buildTemp.length || 1 >= unitTemp.length) {
            return listVo;
        }

        String campusId = campTemp[1];
        String buildingId = buildTemp[1];
        String unitId = unitTemp[1];

        List<Floor> listT =
                list(Wrappers.<Floor>lambdaQuery().eq(Floor::getCampusId, campusId).eq(Floor::getBuildingId,
                        buildingId).eq(Floor::getUnitId, unitId));

        listT.forEach(item-> {
            FloorVo floorVo = new FloorVo();
            BeanUtils.copyProperties(item, floorVo);
            listVo.add(floorVo);
        });

        return listVo;
    }

    @Override
    public List<Floor> getListByOtherId(QueryParams params) {

        List<Floor> list = new ArrayList<>();

        // 架构get 请求参数格式：
//        [name-like~楼栋1, area-like~100]
        List<String> f = params.getF();
        if (2 >= f.size()) {
            return list;
        }

        String campusIdStr = f.get(0);
        String buildingIdStr = f.get(1);
        String unitIdStr = f.get(2);
        if (-1 >= campusIdStr.indexOf("campusId")) {
            return list;
        }
        if (-1 >= buildingIdStr.indexOf("buildingId")) {
            return list;
        }
        if (-1 >= unitIdStr.indexOf("unitId")) {
            return list;
        }

        String[] campTemp = campusIdStr.split(params.VALUE_JOIN);
        String[] buildTemp = buildingIdStr.split(params.VALUE_JOIN);
        String[] unitTemp = unitIdStr.split(params.VALUE_JOIN);

        if (1 >= campTemp.length || 1 >= buildTemp.length || 1 >= unitTemp.length) {
            return list;
        }

        String campusId = campTemp[1];
        String buildingId = buildTemp[1];
        String unitId = unitTemp[1];

        list = list(Wrappers.<Floor>lambdaQuery().eq(Floor::getCampusId, campusId).eq(Floor::getBuildingId,
                        buildingId).eq(Floor::getUnitId, unitId));
        return list;
    }

    @Override
    public Floor getByOtherIdAndName(Long campusId, Long buildingId, Long unitId, String name) {

        if (Objects.isNull(campusId) || Objects.isNull(buildingId) || Objects.isNull(unitId) || StringUtils.isBlank(name)) {
            return new Floor();
        }
        return this.getFirst(Wrappers.<Floor>lambdaQuery().eq(Floor::getCampusId, campusId).eq(Floor::getBuildingId,
                buildingId).eq(Floor::getUnitId, unitId).eq(Floor::getName, name));
    }

    @Override
    public void exportExcel(String filename, QueryParams params, HttpServletResponse resp) {
        SqueryWapper<Floor> squeryWapper = new SqueryWapper<>(Floor.class);

        if (null == squeryWapper) {
            squeryWapper = new SqueryWapper<>(Floor.class);
        }
        QueryWrapper<Floor> wrapper = Wrappers.query();
        squeryWapper.setWhere(params.getF(), wrapper);
        squeryWapper.setSelect(params.getFields(), wrapper);
        squeryWapper.setOrderBy(params.getOrderBy(), wrapper);

        List<Floor> list = new ArrayList<>();
        List<FloorIo> listIo = new ArrayList<>();
        if (null == params.getF()) {
            list.add(new Floor());
            listIo.add(new FloorIo());
        } else {
            list = this.list(wrapper);
        }

        list.forEach(item->{
            Floor floor = this.getData(item.getId());

            FloorIo floorIo = new FloorIo();
            BeanUtils.copyProperties(item, floorIo);
            floorIo.setCampusName(campusService.getEasyVoData(floor.getCampusId()).getName());
            floorIo.setBuildingName(buildingService.getEasyVoData(floor.getBuildingId()).getName());
            floorIo.setUnitName(unitService.getEasyVoData(floor.getUnitId()).getName());

            listIo.add(floorIo);
        });

        if (StringUtils.isBlank(filename)) {
            filename = "楼层";
        }

        // 导出
        ExcelUtil.exportExcel(filename, listIo, resp);
    }

    @Override
    public HttpResult<Void> importExcel(MultipartFile files) {
        List<FloorIo> dataList;
        try {
            dataList = EasyExcel.read(files.getInputStream()).head(FloorIo.class).sheet()
                    .doReadSync();
        } catch (Exception e) {
            return HttpResult.fail("B0000", I18n.build("数据格式存在问题，无法读取！"));
        }
        if (0 >= dataList.size()) {
            return HttpResult.fail("B0000", I18n.build("无数据，无法读取！"));
        }

        AtomicInteger successNum = new AtomicInteger();
        AtomicInteger errorNum = new AtomicInteger();
        dataList.forEach(item-> {
            importExcelHelper(item, successNum, errorNum);
        });

        String message = "总数：" + dataList.size() + "; 成功：" + successNum.get() + "; 失败：" + errorNum.get();
        return HttpResult.success("导入成功 " + message);
    }

    @Override
    public HttpResult<Serializable> updateSort(List<Map<String, Integer>> sortedData) {

        if (null == sortedData || 0 >= sortedData.size()) {
            return HttpResult.fail("4000", "排序数据不可为空", "error");
        }

        sortedData.forEach(item-> {

            if (!item.containsKey("id") || !item.containsKey("orders")) {
                return;
            }

            Long id = item.get("id").longValue();;
            int orders = item.get("orders");

            Floor floor = new Floor();
            floor.setId(id);
            floor.setOrders(orders);
            this.updateById(floor);
        });

        return HttpResult.success("排序成功");
    }

    private void importExcelHelper (FloorIo floorIo, AtomicInteger successNum, AtomicInteger errorNum) {
        String campusName = floorIo.getCampusName();
        String buildingName = floorIo.getBuildingName();
        String unitName = floorIo.getUnitName();

        boolean checkFlag =
                StringUtils.isBlank(campusName) || StringUtils.isBlank(buildingName) || StringUtils.isBlank(unitName) || StringUtils.isBlank(floorIo.getName());

        if (checkFlag) {
            errorNum.getAndIncrement();
            return;
        }

        Floor floor = new Floor();
        BeanUtils.copyProperties(floorIo, floor);


        Campus campus = campusService.getByName(campusName);

        if (null == (campus) && Objects.isNull(campus.getId())) {
            errorNum.getAndIncrement();
            return;
        }
        floor.setCampusId(campus.getId());

        Building building = buildingService.getByCampusIdAndName(campus.getId(), buildingName);

        if (null == (building) || Objects.isNull(building.getId())) {
            errorNum.getAndIncrement();
            return;
        }
        floor.setBuildingId(building.getId());

        Unit unit = unitService.getByCIDAndBIDAndName(campus.getId(), building.getId(), unitName);

        if (null == (unit) || Objects.isNull(unit.getId())) {
            errorNum.getAndIncrement();
            return;
        }
        floor.setUnitId(unit.getId());

        floor.setParentId(floor.getCampusId() + "-" + floor.getBuildingId() + "-" + floor.getUnitId() + "-0");

        try {
            this.save(floor);
            successNum.getAndIncrement();
        } catch (Exception e) {
            e.printStackTrace();
            errorNum.getAndIncrement();
            return;
        }
    }
}
